package com.xinhe.web.service;

import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.QueryResults;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.xinhe.web.common.BusinessException;
import com.xinhe.web.common.Result;
import com.xinhe.web.entity.*;
import com.xinhe.web.reposity.OrderItemRepository;
import com.xinhe.web.reposity.OrderRepository;
import com.xinhe.web.reposity.OrderReturnRepository;
import com.xinhe.web.response.AttachView;
import com.xinhe.web.response.OrderReturnByUserView;
import com.xinhe.web.response.OrderReturnDetailView;
import com.xinhe.web.response.OrderReturnView;
import com.xinhe.web.session.UserSessionManager;
import com.xinhe.web.util.Snowflake;
import com.xinhe.web.weixin.WeixinRefundNotifyView;
import com.xinhe.web.weixin.service.WeixinAppTradeService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
import javax.inject.Provider;
import javax.persistence.EntityManager;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class OrderReturnService {
    @Autowired
    private OrderReturnRepository orderReturnRepository;
    @Autowired
    private OrderItemRepository orderItemRepository;
    @Autowired
    private UserSessionManager userSessionManager;
    @Autowired
    private AttachService attachService;
    @Autowired
    private OrderPayService orderPayService;
    @Autowired
    private OrderRepository orderRepository;
    @Autowired
    private OrderItemService orderItemService;
    @Autowired
    private WeixinAppTradeService weixinAppTradeService;
    @Autowired
    WeixinTradeService weixinTradeService;
    //查询工厂
    private JPAQueryFactory queryFactory;
    @Autowired
    private Provider<EntityManager> entityManager;
    @PostConstruct
    public void init() {
        queryFactory = new JPAQueryFactory(entityManager);
    }

    public QueryResults<OrderReturnView> pageOrderReturn(Long userId, Long sellerUserId, Long orderId, int pageNum, int pageSize) {
        QOrderReturn qOrderReturn = QOrderReturn.orderReturn;
        QMember qMember = QMember.member;
        QOrder qOrder = QOrder.order;
        QOrderItem qOrderItem = QOrderItem.orderItem;
        QGoodsPrice qGoodsPrice = QGoodsPrice.goodsPrice;

        BooleanBuilder builder = new BooleanBuilder();
        if (!Objects.isNull(userId)){
            builder.and(qOrderReturn.userId.eq(userId));
        }
        if (!Objects.isNull(sellerUserId)){
            builder.and(qOrder.sellerUserId.eq(sellerUserId));
        }
        if (!Objects.isNull(orderId)){
            builder.and(qOrderReturn.orderId.eq(orderId));
        }
        return queryFactory.select(
                Projections.bean(
                        OrderReturnView.class,
                        qOrderReturn.id,
                        qOrderReturn.userId,
                        qOrderReturn.orderId,
                        qOrderReturn.orderItemId,
                        qOrderReturn.status,
                        qOrderReturn.returnType,
                        qOrderReturn.returnFee,
                        qOrderReturn.checkRemark,
                        qOrderReturn.cause,
                        qMember.nickname,
                        qMember.mobile,
                        qMember.name,
                        qMember.iconPath.as("userIconPath"),
                        qOrderItem.iconPath.as("goodsIconPath"),
                        qOrderItem.goodsName,
                        qGoodsPrice.name.as("priceName")

                )
        ).from(qOrderReturn)
                .innerJoin(qMember).on(qOrderReturn.userId.eq(qMember.fUserId))
                .innerJoin(qOrder).on(qOrderReturn.orderId.eq(qOrder.id))
                .innerJoin(qOrderItem).on(qOrderReturn.orderItemId.eq(qOrderItem.id))
                .innerJoin(qGoodsPrice).on(qOrderItem.goodsPriceId.eq(qGoodsPrice.id))
                .where(builder).offset(pageNum * pageSize).limit(pageSize).fetchResults();

    }

    public QueryResults<OrderReturnView> pageOrderReturnBySeller(Long sellerUserId,int pageNum, int pageSize) {
        if (Objects.isNull(sellerUserId)){
            sellerUserId = this.userSessionManager.getUserId();
        }
        QOrderReturn qOrderReturn = QOrderReturn.orderReturn;
        QMember qMember = QMember.member;
        QOrder qOrder = QOrder.order;
        QOrderItem qOrderItem = QOrderItem.orderItem;
        QGoodsPrice qGoodsPrice = QGoodsPrice.goodsPrice;
        BooleanBuilder builder = new BooleanBuilder();
        if (!Objects.isNull(sellerUserId)){
            builder.and(qOrder.sellerUserId.eq(sellerUserId));
        }
        return queryFactory.select(
                Projections.bean(
                        OrderReturnView.class,
                        qOrderReturn.id,
                        qOrderReturn.userId,
                        qOrderReturn.orderId,
                        qOrderReturn.orderItemId,
                        qOrderReturn.status,
                        qOrderReturn.returnType,
                        qOrderReturn.returnFee,
                        qOrderReturn.checkRemark,
                        qOrderReturn.cause,
                        qMember.nickname,
                        qMember.mobile,
                        qMember.name,
                        qMember.iconPath.as("userIconPath"),
                        qOrderItem.iconPath.as("goodsIconPath"),
                        qOrderItem.goodsName,
                        qGoodsPrice.name.as("priceName")

                )
        ).from(qOrderReturn)
                .innerJoin(qMember).on(qOrderReturn.userId.eq(qMember.fUserId))
                .innerJoin(qOrder).on(qOrderReturn.orderId.eq(qOrder.id))
                .innerJoin(qOrderItem).on(qOrderReturn.orderItemId.eq(qOrderItem.id))
                .innerJoin(qGoodsPrice).on(qOrderItem.goodsPriceId.eq(qGoodsPrice.id))
                .where(builder).offset(pageNum * pageSize).limit(pageSize).fetchResults();
    }

    public QueryResults<OrderReturnByUserView> pageOrderReturnByUser(Long userId, int pageNum, int pageSize) {
        if (Objects.isNull(userId)){
            userId = this.userSessionManager.getUserId();
        }
        QOrderReturn qOrderReturn = QOrderReturn.orderReturn;
        QOrderItem qOrderItem = QOrderItem.orderItem;
        QGoods qGoods = QGoods.goods;
        QSellerShop qSellerShop = QSellerShop.sellerShop;
        BooleanBuilder builder = new BooleanBuilder();
        if (!Objects.isNull(userId)){
            builder.and(qOrderReturn.userId.eq(userId));
        }
        return queryFactory.select(
                Projections.bean(
                        OrderReturnByUserView.class,
                        qOrderReturn.id,
                        qOrderReturn.userId,
                        qOrderReturn.orderId,
                        qOrderReturn.orderItemId,
                        qOrderReturn.status,
                        qOrderReturn.returnType,
                        qOrderReturn.returnFee,
                        qOrderReturn.checkRemark,
                        qOrderReturn.cause,
                        qOrderItem.iconPath.as("goodsIconPath"),
                        qGoods.id.as("goodsId"),
                        qGoods.name.as("goodsName"),
                        qGoods.iconPath.as("goodsIconPath"),
                        qGoods.dis.as("goodsDes"),
                        qGoods.sellerUserId,
                        qSellerShop.name.as("sellerShopName"),
                        qSellerShop.iconPath.as("sellerIconPath")

                )
        ).from(qOrderReturn)
                .innerJoin(qOrderItem).on(qOrderReturn.orderItemId.eq(qOrderItem.id))
                .leftJoin(qGoods).on(qOrderItem.goodsId.eq(qGoods.id))
                .leftJoin(qSellerShop).on(qGoods.sellerUserId.eq(qSellerShop.fUserId))
                .where(builder).offset(pageNum * pageSize).limit(pageSize).fetchResults();
    }

    @Transactional
    //@ANoRepeatRequest
    public Result saveOrderReturn(Long orderItemId,String returnType,String cause,String remark,Set<Long> attachIds) {
        Long userId = this.userSessionManager.getUserId();
        OrderItem orderItem = this.orderItemRepository.findById(orderItemId).get();
        if (!"PAYED".equals(orderItem.getStatus()) &&
                !"SENDED".equals(orderItem.getStatus()) &&
                !"RECEIVED".equals(orderItem.getStatus()) &&
                !"COMMENTED".equals(orderItem.getStatus())) {
            return Result.failed(101,"当前订单商品无法申请退款");
        }
        //签收时间超过三天，不允许退款
        Order order = this.orderRepository.findById(orderItem.getOrderId()).get();
        if (order.getReceiveTime() != null) {
            Calendar instance = Calendar.getInstance();
            instance.setTime(order.getReceiveTime());
            instance.add(5, 3);
            Calendar calendar = Calendar.getInstance();
            if (calendar.getTime().compareTo(instance.getTime()) > 0) {
                return Result.failed(102,"当前订单商品无法退款");
            }
        }
        OrderReturn orderReturn = new OrderReturn();
        orderReturn.setId(Snowflake.generateId());
        orderReturn.setOrderId(orderItem.getOrderId());
        orderReturn.setOrderItemId(orderItem.getId());
        orderReturn.setReturnFee(orderItem.getItemPrice());
        orderReturn.setStatus("APPLY");
        orderReturn.setReturnType(returnType);
        orderReturn.setUserId(userId);
        orderReturn.setCause(cause);
        //orderReturn.setRemark(model.getRemark());
        this.orderReturnRepository.save(orderReturn);
        if (CollectionUtils.isNotEmpty(attachIds)) {
            this.attachService.updateAttachByBusinessIdAndAttachIds(orderReturn.getId(), attachIds);
        }
        this.orderItemRepository.updateStatusByOrderItemId(orderItem.getId(),"SERVICE_APPLY");
        Integer count = this.orderItemRepository.countByOrderIdAndStatues(orderItem.getOrderId(), new HashSet(Arrays.asList((Object[])new String[] { "PAYED"
                , "SENDED","RECEIVED","COMMENTED" })));
        if (count.intValue() == 0) {
            this.orderRepository.updateStatusById(orderItem.getOrderId(), "AFTER_SALE_SERVICE");
        }
        return Result.ok();
    }

    @Transactional
    //@ANoRepeatRequest
    public Result checkOrderReturn(String result,String remark,Set<Long> ids) {
        List<OrderReturn> orderReturnList = this.orderReturnRepository.findAllById(ids);
        if (CollectionUtils.isNotEmpty(orderReturnList)) {
            for (OrderReturn orderReturn : orderReturnList) {
                if (!orderReturn.getStatus().equals("APPLY")) {
                    throw new BusinessException(101,"你所选的退款中包含已审核的退款");
                }
                OrderItem orderItem = (OrderItem)this.orderItemRepository.findById(orderReturn.getOrderItemId()).get();
                if ("SUCCESS".equals(result)) {
                    if (orderReturn.getReturnType().equals("BARTER")) {
                        orderReturn.setStatus("SUCCESS");
                    } else {
                        Result res = this.orderPayService.saveItemRefund(orderItem);
                        if (0!=res.getCode()) {
                            throw new BusinessException(102,res.getMessage());
                        }
                        if ("DOING".equals((String) res.getData())) {
                            orderReturn.setStatus("DOING");
                        } else {
                            orderReturn.setStatus("SUCCESS");
                        }
                    }
                    orderItem.setStatus("SERVICE_SUCCESS");
                } else {
                    orderReturn.setStatus("REJECT");
                    orderItem.setStatus("SERVICE_REJECT");
                }
                orderReturn.setCheckRemark(remark);
                this.orderItemRepository.saveAndFlush(orderItem);
            }
            //更新
            this.orderReturnRepository.saveAll(orderReturnList);
        }
        return Result.ok();
    }


    public Result detailOrderReturn(Long orderReturnId) {
        OrderReturnDetailView view = new OrderReturnDetailView();
        OrderReturn orderReturn = (OrderReturn)this.orderReturnRepository.findById(orderReturnId).get();
        if (null != orderReturn) {
            BeanUtils.copyProperties(orderReturn, view);
            view.setReturnType(orderReturn.getReturnType());
            view.setStatus(orderReturn.getStatus());

            OrderItem orderItem = this.orderItemRepository.findById(view.getOrderItemId()).get();
            view.setOrderItem(orderItem);

            List<AttachView> attachViews = this.attachService.findByBusinessId(orderReturn.getId());
            if (CollectionUtils.isNotEmpty(attachViews)) {
                view.setPaths((List)attachViews.stream().map(AttachView::getPath).collect(Collectors.toList()));
            }
        }
        return Result.ok(view);
    }


    @Transactional
    public String responseWeixinOrderItemRefundNotify(Long configId) {
        Result<WeixinRefundNotifyView> result = this.weixinTradeService.getWeixinRefundNotifyDataAndValidateAndUpdateWeixinTrade(configId);
        if (0!=result.getCode()) {
            return result.getMessage();
        }
        WeixinRefundNotifyView refundView = (WeixinRefundNotifyView)result.getData();
        OrderReturn orderReturn = (OrderReturn)this.orderReturnRepository.findById(refundView.getDataId()).get();
        if (orderReturn != null && "DOING".equals(orderReturn.getStatus())) {
            orderReturn.setStatus("SUCCESS");
            this.orderReturnRepository.saveAndFlush(orderReturn);
        }
        return result.getMessage();
    }

    @Transactional
    public String responseWeixinOrderRefundNotify(Long configId) {
        Result<WeixinRefundNotifyView> result = this.weixinTradeService.getWeixinRefundNotifyDataAndValidateAndUpdateWeixinTrade(configId);
        if (0!=result.getCode()) {
            return result.getMessage();
        }
        WeixinRefundNotifyView refundView = (WeixinRefundNotifyView)result.getData();
        Order order = (Order)this.orderRepository.findById(refundView.getDataId()).get();
        if (order != null && "UN_PAY".equals(order.getStatus())) {
            order.setStatus("CANCEL");
            this.orderRepository.saveAndFlush(order);
            this.orderItemRepository.updateStatusByOrderId(order.getId(),"REFUNDED");
        }
        return result.getMessage();
    }

    public Result delete(Long orderReturnId) {
        orderReturnRepository.deleteById(orderReturnId);
        return Result.ok();
    }
}
